﻿using System;
using System.Collections;
using UnityEngine;
namespace UnityModule
{
    public class CoroutineItem
    {
        private Action m_Action;
        private bool m_IsDispose;

        public bool IsDisposed
        {
            get
            {
                return m_IsDispose;
            }
        }

        public Action Action
        {
            get
            {
                return m_Action;
            }
        }

        public CoroutineItem(Action action)
        {
            m_Action = action;
            m_IsDispose = false;
        }

        public void Invoke()
        {
            m_Action?.Invoke();
        }

        public void Dispose()
        {
            m_IsDispose = true;
            m_Action = null;
        }
    }
    /// <summary>
    /// 协同工具
    /// </summary>
    public class CoroutineComponent : SingletonBehaviour<CoroutineComponent>
    {
        public void WaitForEndOfFrame(CoroutineItem callBack)
        {
            StartCoroutine(WaitForEndOfFrameCallBack(callBack));
        }

        public void WaitForSeconds(float time, CoroutineItem callBack)
        {
            StartCoroutine(WaitForSecondsCallBack(time, callBack));
        }

        public void WaitOneFrame(CoroutineItem callBack)
        {
            StartCoroutine(WaitOneFrameToCall(callBack));
        }

        public void WaitForEndOfFrame(Action action)
        {
            StartCoroutine(WaitForEndOfFrameCallBack(action));
        }

        public void WaitForSeconds(float time, Action action)
        {
            StartCoroutine(WaitForSecondsCallBack(time, action));
        }

        public void WaitOneFrame(Action action)
        {
            StartCoroutine(WaitOneFrameToCall(action));
        }

        private IEnumerator WaitForSecondsCallBack(float time, CoroutineItem callBack)
        {
            yield return new WaitForSeconds(time);
            TryInvoke(callBack);
        }

        private IEnumerator WaitForEndOfFrameCallBack(CoroutineItem callBack)
        {
            yield return new WaitForEndOfFrame();
            TryInvoke(callBack);
        }
        private IEnumerator WaitOneFrameToCall(CoroutineItem callBack)
        {
            yield return null;
            TryInvoke(callBack);
        }

        private IEnumerator WaitForSecondsCallBack(float time, Action action)
        {
            yield return new WaitForSeconds(time);
            action?.Invoke();
        }

        private static WaitForEndOfFrame s_FrameEndMark = null;
        public static WaitForEndOfFrame FrameEndMark
        {
            get
            {
                if (null == s_FrameEndMark)
                    s_FrameEndMark = new WaitForEndOfFrame();
                return s_FrameEndMark;
            }
        }
        private IEnumerator WaitForEndOfFrameCallBack(Action action)
        {
            yield return FrameEndMark;
            action?.Invoke();
        }
        private IEnumerator WaitOneFrameToCall(Action action)
        {
            yield return null;
            action?.Invoke();
        }

        private void TryInvoke(CoroutineItem callBack)
        {
            if (null != callBack && !callBack.IsDisposed)
            {
                callBack.Invoke();
                callBack.Dispose();
            }
        }
    }

}
